﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using ProfileManager.Properties;

namespace ProfileManager.Helpers
{
    public class Crypto
    {
        public static string GetMd5Sum(string data)
        {
            try
            {
                byte[] input = Encoding.Default.GetBytes(data);
                byte[] result = MD5.Create().ComputeHash(input);

                return Convert.ToBase64String(result);
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
            
        }

        public static byte[] Encrypt(object data)
        {
            try
            {
                if (Resources.CryptoKey != null && Resources.CryptoIV != null && data != null)
                {
                    return EncryptObjectToBytes(data, Convert.FromBase64String(Resources.CryptoKey),
                                                Convert.FromBase64String(Resources.CryptoIV));
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        public static string Decrypt(byte[] protectedData)
        {
            try
            {
                if (Resources.CryptoKey != null && Resources.CryptoIV != null && protectedData != null)
                {
                    return DecryptStringFromBytes(protectedData, Convert.FromBase64String(Resources.CryptoKey),
                                                  Convert.FromBase64String(Resources.CryptoIV));
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static byte[] EncryptObjectToBytes(object data, byte[] key, byte[] iv)
        {
            try
            {
                if (data != null)
                {
                    byte[] encrypted;

                    using (Rijndael rijAlg = Rijndael.Create())
                    {
                        rijAlg.Key = key;
                        rijAlg.IV = iv;

                        ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

                        using (MemoryStream msEncrypt = new MemoryStream())
                        {
                            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                            {
                                using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                                {
                                    swEncrypt.Write(data);
                                }
                                encrypted = msEncrypt.ToArray();
                            }
                        }
                    }
                    return encrypted;
                }
                throw new ArgumentNullException("data");
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }

        private static string DecryptStringFromBytes(byte[] cipherText, byte[] key, byte[] iv)
        {
            try
            {
                if (cipherText != null && cipherText.Length > 0)
                {
                    string plaintext;

                    using (Rijndael rijAlg = Rijndael.Create())
                    {
                        rijAlg.Key = key;
                        rijAlg.IV = iv;

                        ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

                        using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                        {
                            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                            {
                                using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                                {
                                    plaintext = srDecrypt.ReadToEnd();
                                }
                            }
                        }
                    }
                    return plaintext;
                }
                throw new ArgumentNullException("cipherText");
            }
            catch(Exception ex)
            {
                Logger.WriteLog(ex);
                return null;
            }
        }
    }
}
